package se.nikmel.AnDisper.UI;

import java.util.ArrayList;
import java.util.List;

import se.nikmel.AnDisper.MainActivity;
import se.nikmel.AnDisper.R;
import se.nikmel.AnDisper.Display.DisperDisplay;
import se.nikmel.AnDisper.Display.DisplaySetup;
import se.nikmel.AnDisper.Display.DisplaySetup.E_CONFIGURATION;
import android.app.Activity;
import android.app.AlertDialog;
import android.app.AlertDialog.Builder;
import android.app.ProgressDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.graphics.Color;
import android.os.AsyncTask;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.AdapterView.OnItemClickListener;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.TextView;

public class UI_DisplayConfig_Controller implements I_UI_ViewController {
	// Misc
	private static final String TAG = "UI_MainScreenController"; // Logging tag
	private final int LAYOUT_ID = R.layout.scr_displaysetup;
	//
	@SuppressWarnings("unused")
	private int m_iLayoutID;
	private MainActivity m_actParent;
	// UI Controls on the screen
	private View m_scrDisplays;
	private ListView m_lvwScreenSetup;
	private TextView m_txtTitle;
	private TextView m_txtServerName;
	private LinearLayout m_lnrTitle;

	// Vars
	private String m_sLastUpdateServerIP;
	private _RefreshDisplaysTask m_tskRefresh;
	private OnDisperConnectionError m_oConnectionErrorListener;

	public UI_DisplayConfig_Controller(MainActivity p_actParent) {
		m_actParent = p_actParent;
		m_sLastUpdateServerIP = null;
		m_oConnectionErrorListener = null;
		m_tskRefresh = null;
		// Load the screen
		LayoutInflater oInflater = m_actParent.getLayoutInflater();
		m_scrDisplays = oInflater.inflate(LAYOUT_ID, null);
		m_lnrTitle = (LinearLayout) m_scrDisplays
				.findViewById(R.id.lnrDispTitle);
		m_lnrTitle.setBackgroundColor(Color.DKGRAY);

		m_txtServerName = (TextView) m_scrDisplays
				.findViewById(R.id.txtDispServerName);
		m_txtServerName.setBackgroundColor(Color.TRANSPARENT);

		m_lvwScreenSetup = (ListView) m_scrDisplays
				.findViewById(R.id.lvwScreenSetup);
		m_txtTitle = (TextView) m_scrDisplays.findViewById(R.id.txtDispTitle);
		m_txtTitle.setBackgroundColor(Color.DKGRAY);
		m_txtTitle.setShadowLayer(2.5f, 3.0f, 3.0f, Color.BLACK);
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see se.nikmel.AnDisper.UI_ViewController#getView()
	 */
	public View getView() {

		return m_scrDisplays;

	}

	public void pause() {
		// Cancel refreshtask
		if (m_tskRefresh != null)
			m_tskRefresh.cancel(true);
	}

	public void resume() {
		if (m_sLastUpdateServerIP == null
				|| !m_sLastUpdateServerIP.equals(m_actParent.getDisperServer()
						.getServerIP()))

			refresh();

	}

	/*
	 * *********************** Privata metoder
	 */
	public void refresh() {
		if (m_tskRefresh == null) {
			m_tskRefresh = new _RefreshDisplaysTask();
			m_tskRefresh.execute((Void) null);
		}
	}

	public void setOnConectionErrorListener(OnDisperConnectionError p_oListener) {
		m_oConnectionErrorListener = p_oListener;
	}

	private void fireConnectionFailed(String p_sMessage) {
		if (m_oConnectionErrorListener != null)
			m_oConnectionErrorListener.onConnectionError(p_sMessage);
		else
			Log.w(TAG,
					"(WW) Disper connection error occured but no one listens (displays)...");
	}

	// Applicera vald screen-setup (visa en Ok/Cancel-ruta)
	// Helper till m_lvwScreenSetup
	private class _ApplyScreenSetup implements OnItemClickListener {
		private Activity m_oOwner;

		public _ApplyScreenSetup(Activity p_oOwner) {
			m_oOwner = p_oOwner;
		}

		public void onItemClick(AdapterView<?> arg0, View arg1, int arg2,
				long arg3) {
			final DisplaySetup oSetup = (DisplaySetup) arg1.getTag();
			// 1. Fråga om man är säker
			Builder dlgConfirmation = new AlertDialog.Builder(m_oOwner);
			int ICON_SIZE = 128;
			// dlgConfirmation.setIcon(oSetup.getConfiguration()==E_CONFIGURATION.SINGLE?
			// R.drawable.ic_single_display: R.drawable.ic_dual_display);
			ImageView imgIcon = new ImageView(m_actParent);
			imgIcon.setMinimumHeight(ICON_SIZE);
			imgIcon.setMinimumWidth(ICON_SIZE);
			imgIcon.setMaxHeight(ICON_SIZE);
			imgIcon.setMaxWidth(ICON_SIZE);
			imgIcon.setAdjustViewBounds(true);
			imgIcon.setScaleType(ImageView.ScaleType.FIT_CENTER);
			imgIcon.setImageResource(oSetup.getConfiguration() == E_CONFIGURATION.SINGLE ? R.drawable.ic_single_display
					: R.drawable.ic_dual_display);
			dlgConfirmation.setIcon(imgIcon.getDrawable());
			dlgConfirmation
					.setTitle(oSetup.getConfiguration() == E_CONFIGURATION.SINGLE ? "Single screen"
							: "Dual screen");
			dlgConfirmation.setMessage(oSetup.toString());
			dlgConfirmation.setCancelable(false);
			dlgConfirmation.setNegativeButton(android.R.string.cancel, null);
			dlgConfirmation.setPositiveButton("Switch",
					new DialogInterface.OnClickListener() {
						public void onClick(DialogInterface dialog, int which) {
							new _ApplyDisplaySetupTask().execute(oSetup);							
						}
					});

			dlgConfirmation.create().show();

		}

	}

	// Custom Adapter for the Listview to display icons and heading +
	// description per item
	private class _MyDisplaysAdapter extends ArrayAdapter<DisplaySetup> {
		private final Context context;
		private final DisplaySetup[] values;

		public _MyDisplaysAdapter(Context context, DisplaySetup[] values) {
			super(context, R.layout.cell_layout_displays, values);
			this.context = context;
			this.values = values;
		}

		@Override
		public View getView(int position, View convertView, ViewGroup parent) {
			LayoutInflater inflater = (LayoutInflater) context
					.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
			View rowView = inflater.inflate(R.layout.cell_layout_displays,
					null, false);
			TextView txtDispHeading = (TextView) rowView
					.findViewById(R.id.txtDisplayHeading);
			TextView txtDispDescr = (TextView) rowView
					.findViewById(R.id.txtDisplaysDescr);
			ImageView imgIcon = (ImageView) rowView.findViewById(R.id.imgIcon);
			if (values.length == 1 && values[0] == null) {
				txtDispHeading.setText("No connection found!");
				imgIcon.setImageResource(R.drawable.ic_error);
				txtDispDescr.setText("");
				return rowView;
			}

			else if (values[position].getConfiguration() == E_CONFIGURATION.SINGLE) {
				txtDispHeading.setText("Single Display");
				imgIcon.setImageResource(R.drawable.ic_single_display);
			}

			else {
				txtDispHeading.setText("Dual Display");
				imgIcon.setImageResource(R.drawable.ic_dual_display);
			}
			txtDispDescr.setText(values[position].toString());
			rowView.setTag(values[position]);
			return rowView;
		}
	}

	private class _ApplyDisplaySetupTask extends
			AsyncTask<DisplaySetup, Void, Void> {

		@Override
		protected Void doInBackground(DisplaySetup... params) {
			DisplaySetup oSetup = params[0];
			m_actParent.getDisperServer().setDisplays(oSetup);
			
			return (Void) null;
		}
	}

	/**
	 * Task to request and display a list of available displays from server.
	 * Fires a ConnectionError event if communication w/ server fails.
	 * 
	 * @author niklas
	 * 
	 */
	private class _RefreshDisplaysTask extends AsyncTask<Void, Void, Boolean> {

		private ProgressDialog m_uiProgress;
		private List<DisperDisplay> m_lstDisplays;;

		@Override
		protected Boolean doInBackground(Void... params) {

			Log.v(TAG, "(II) In refreshDisplays (doInBackground)");

			m_lstDisplays = m_actParent.getDisperServer().getDisplays();
			Log.v(TAG, "(II) After refreshDisplays");
			if (m_lstDisplays == null || this.isCancelled())
				return false;
			else
				return true;
		}

		@Override
		protected void onCancelled() {
			super.onCancelled();
			Log.v(TAG, "(II) RefreshDisplays task was cancelled!");
			m_uiProgress.dismiss();
			m_tskRefresh = null;
		}

		@Override
		protected void onPostExecute(Boolean result) {
			super.onPostExecute(result);
			m_tskRefresh = null;

			if (result) {
				// Skapa adapter för listvyn
				List<DisplaySetup> lstSetups = new ArrayList<DisplaySetup>();

				if (m_lstDisplays == null || this.isCancelled()) {
					DisplaySetup[] arrSetups = new DisplaySetup[1];
					arrSetups[0] = null;
					m_lvwScreenSetup.setEnabled(false);
					m_lvwScreenSetup.setAdapter(new _MyDisplaysAdapter(
							m_actParent, arrSetups));
				} else {
					// Single-screen setups
					for (DisperDisplay dspDisplay : m_lstDisplays) {
						DisplaySetup oDisp = new DisplaySetup(dspDisplay);
						lstSetups.add(oDisp);
					}
					// Exakt 2 skärmar...
					if (m_lstDisplays.size() >= 2) {
						DisplaySetup oDisplay;

						oDisplay = new DisplaySetup(m_lstDisplays.get(0),
								m_lstDisplays.get(1));
						lstSetups.add(oDisplay);

						oDisplay = new DisplaySetup(m_lstDisplays.get(1),
								m_lstDisplays.get(0));
						lstSetups.add(oDisplay);
					}
					m_lvwScreenSetup.setEnabled(true);
					// else if (arrDisplays.size() > 2) {
					//
					// lstStrings.add("Too many screens, cant be bothered!");
					// m_lvwScreenSetup.setEnabled(false);
					// }

				}

				DisplaySetup[] arrSetups = new DisplaySetup[lstSetups.size()];
				m_lvwScreenSetup.setAdapter(new _MyDisplaysAdapter(m_actParent,
						lstSetups.toArray(arrSetups)));

				m_lvwScreenSetup.setOnItemClickListener(new _ApplyScreenSetup(
						m_actParent));

				m_sLastUpdateServerIP = m_actParent.getDisperServer()
						.getServerIP();
				m_txtServerName.setText(m_actParent.getDisperServer()
						.getHostname());
				m_txtServerName.setVisibility(View.VISIBLE);
			}
			m_uiProgress.dismiss();

			// Success?
			if (!result)
				fireConnectionFailed("Failed to retreive available displays from server!");

		}

		@Override
		protected void onPreExecute() {
			m_uiProgress = ProgressDialog.show(m_actParent, "Updating...",
					"Requesting available displays from server", true);
			super.onPreExecute();
		}

	}
}
